/*
 * @Author: 13177709051 3506463075@qq.com
 * @Date: 2024-11-14 13:46:45
 * @LastEditors: 13177709051 3506463075@qq.com
 * @LastEditTime: 2024-11-21 22:30:23
 * @FilePath: /linux33/UdpServerMain.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "UdpServer.hpp"
#include "Dict.hpp"

#include <memory>

// ./udp_server local-port
// ./udp_server 8888
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " local-port" << std::endl;
        exit(0);
    }
    uint16_t port = std::stoi(argv[1]);
    EnableScreen();

    Dict dict("./dict.txt");
    // std::bind 是 C++11 中引入的一个函数模板，用于生成一个新的可调用对象，绑定一个函数或成员函数到特定的对象和参数。通过 std::bind，可以创建一个新的函数或可调用对象，其中的某些参数被预设定或绑定，而其他参数则可以在调用时动态传入。
    // std::bind 返回一个新的可调用对象，该对象接受一个或多个参数，并将这些参数传递给绑定的函数。绑定的函数可以是普通函数、成员函数或函数对象
    func_t translate = std::bind(&Dict::Translate, &dict, std::placeholders::_1);
    
    std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>(translate, port); //C++14的标准
    usvr->InitServer();
    usvr->Start();
    return 0;
}


// std::unique_ptr 是 C++11 引入的智能指针，用来管理动态分配的对象（通常是通过 new 创建的）。与传统的指针不同，std::unique_ptr 会在其生命周期结束时自动销毁所管理的对象，从而避免了手动释放内存的麻烦，减少了内存泄漏的风险。
// std::unique_ptr<UdpServer> 表示 usvr 是一个指向 UdpServer 类型对象的智能指针。
// unique_ptr 的特点：
// 它是独占所有权的，意味着一个 unique_ptr 对象在同一时刻只能拥有某个资源的所有权。
// unique_ptr 不支持复制操作，但支持移动操作。
// 其资源会在 unique_ptr 被销毁时自动释放，通常通过析构函数来删除动态分配的对象。

// std::make_unique 是 C++14 引入的一个方便的工厂函数，用于创建一个 std::unique_ptr 并直接初始化指向的对象。它的好处是避免了直接使用 new 关键字，简化了代码并减少了错误的可能性（例如忘记手动释放内存）。
// std::make_unique<UdpServer>(translate, port) 会：
// 创建一个新的 UdpServer 对象，使用 translate 和 port 作为构造函数的参数来初始化该对象。
// 返回一个指向该新创建对象的 std::unique_ptr，该智能指针会自动管理这个对象的生命周期。

// 参数 1：&Dict::Translate
// &Dict::Translate 是成员函数指针，指向 Dict 类中的 Translate 方法。假设 Dict 类有一个成员函数 Translate，S其签名可能是：
// std::string Dict::Translate(const std::string& word);
// &Dict::Translate 就是这个成员函数的指针，意味着我们将要调用 Dict 类的 Translate 方法。
// 参数 2：&dict
// &dict 是指向 Dict 类对象 dict 的指针。std::bind 需要知道目标对象是哪一个，以便在调用时使用该对象来执行成员函数。
// 也就是说，这里的 &dict 告诉 std::bind 要调用 dict 对象上的 Translate 方法。
// 参数 3：std::placeholders::_1
// std::placeholders::_1 是一个占位符，表示将来调用绑定的函数时，第一个参数将会在调用时动态提供。
// 这个占位符告诉 std::bind 需要一个参数，并且会在 translate 被调用时传递给 Dict::Translate 的第一个参数。具体来说，std::placeholders::_1 将会被调用时传入的第一个实参替换。


// 这段代码实现了一个基于 UdpServer 的 UDP 服务器，目的是通过翻译字典（由 Dict 类提供的功能）处理客户端发送的请求。通过网络通信，服务器接收客户端发来的数据，根据字典内容进行翻译并返回结果。

// int main(int argc, char *argv[])
// 命令行参数检查：main 函数首先检查传入的参数数量。如果参数不等于 2（即程序名和端口号），则打印使用说明并退出。参数的第一个是程序名，第二个是本地监听端口。
// argv[0]：程序本身的路径或名称。
// argv[1]：传入的本地端口号，用于 UDP 服务器的绑定。

// 端口号解析
// 端口号转换：通过 std::stoi() 函数将命令行输入的字符串 argv[1] 转换为 uint16_t 类型的端口号。这个端口号将用来绑定 UDP 套接字。

// 启用屏幕输出
// 这里调用了 EnableScreen() 函数，它用于初始化或启用屏幕输出/日志记录功能。

// 创建 Dict 对象
// 字典文件加载：创建一个 Dict 类的实例 dict，并从文件 dict.txt 加载字典内容。该文件路径传递给 Dict 的构造函数

// 创建翻译回调函数
// 创建回调函数：这里使用了 std::bind 来绑定 Dict 类的成员函数 Translate，将 dict 对象和 std::placeholders::_1 作为占位符传递给回调函数。std::placeholders::_1 代表传递给回调函数的第一个参数。
// std::bind(&Dict::Translate, &dict, std::placeholders::_1) 会返回一个新的可调用对象 translate，它能够接收一个 std::string 类型的参数并调用 dict.Translate() 方法进行翻译。

// 创建 UdpServer 对象
// 创建 UDP 服务器：使用 std::make_unique<UdpServer> 创建一个 UdpServer 对象，并传递 translate 回调函数和端口号 port。
// 这意味着 UDP 服务器将在启动时使用传入的端口号进行绑定，并将 translate 作为数据处理的回调函数。当服务器接收到数据时，它将调用 translate 函数来处理收到的数据并返回结果。

// 初始化和启动服务器
// 初始化服务器：usvr->InitServer() 初始化服务器，创建套接字并绑定端口。这一步会创建 UDP 套接字并将其绑定到本地端口 port。
// 启动服务器：usvr->Start() 启动服务器，开始接收客户端的请求并处理数据。这个方法会进入一个循环，不断接收客户端数据，并调用 translate 函数进行处理后发送回响应。